﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Net;
using System.Reflection;

namespace Landscape.XSLT
{
    public class Library : BaseExtension
    {
        private Dictionary<string, string> sessionSettings;

        public Library(ref Dictionary<string, string> sessionSettings)
        {
            this.sessionSettings = sessionSettings;
        }

        /// <summary>
        /// Gets a variable from the HTTP POST collection
        /// </summary>
        /// <param name="varName">the variable name</param>
        /// <returns>The variable value</returns>
        public string RequestForm(string varName) { 
            if(System.Web.HttpContext.Current != null && !string.IsNullOrEmpty(System.Web.HttpContext.Current.Request.Form[varName])){
                return System.Web.HttpContext.Current.Request.Form[varName];
            }else{
                return "";
            }
        }

        /// <summary>
        /// Gets a variable from the HTTP GET collection
        /// </summary>
        /// <param name="varName">the variable name</param>
        /// <returns>The variable value</returns>
        public string RequestQueryString(string varName) {
            if(System.Web.HttpContext.Current != null && !string.IsNullOrEmpty(System.Web.HttpContext.Current.Request.QueryString[varName])){
                return System.Web.HttpContext.Current.Request.QueryString[varName];
            }else{
                return "";
            }
        }


        /// <summary>
        /// Returns selected string in lowercase
        /// </summary>
        /// <param name="s">the string</param>
        /// <returns>A lowercase string</returns>
        public string ToLower(string s){
            return s.ToLower();
        }

        /// <summary>
        /// Returns selected string in uppercase
        /// </summary>
        /// <param name="s">the string</param>
        /// <returns>An uppercase string</returns>
        public string ToUpper(string s)
        {
            return s.ToUpper();
        }

        /// <summary>
        /// Returns selected string with the first letter capitalized
        /// </summary>
        /// <param name="s">the string</param>
        /// <returns>A string with the first letter capitalized</returns>
        public string UCFirst(string s)
        {
            return Globals.UCFirst(s);
        }

        /// <summary>
        /// Returns the value parameter when not empty, defaultValue otherWise
        /// </summary>
        /// <param name="value">The value to return</param>
        /// <param name="defaultValue">The alternate value</param>
        /// <returns></returns>
        public static string GetValue(string value, string defaultValue) {
            value = value.Trim();

            return value.Length > 0 ? value : defaultValue;
        }

        /// <summary>
        /// Remove html tags
        /// </summary>
        /// <param name="s">The HTML String</param>
        /// <returns></returns>
        public string RemoveHTML(string s) {
            string output = Regex.Replace(s, "<[^>]*>", "");
            return output;
        }
        /// <summary>
        /// returns desired application setting.    
        /// check for null values also to prevent null values
        /// </summary>
        /// <param name="settingName"></param>
        /// <returns></returns>
        public string AppSetting(string settingName) {
            string settingValue = System.Configuration.ConfigurationManager.AppSettings[settingName];
            return settingValue != null? settingValue: string.Empty;     
        }

        [Obsolete]
        public string LibSetting(string settingName)
        {
            return string.Empty;
        }

        // settings valid only for this session
        public string SessionSetting(string settingName) {
            return this.sessionSettings.ContainsKey(settingName) && !string.IsNullOrEmpty(this.sessionSettings[settingName]) ? this.sessionSettings[settingName] : string.Empty;
        }

        /// <summary>
        /// Performs string replacement into the supplied source
        /// </summary>
        /// <param name="source">The source string</param>
        /// <param name="match">The string to match</param>
        /// <param name="replace">The selected replacement</param>
        /// <returns>A string with all the occurrences of 'match' replaced by 'replace'</returns>
        public string Replace(string source, string match, string replace) {
            return source.Replace(match, replace);
        }

        /// <summary>
        /// Convert newline characters to br tags
        /// </summary>
        /// <param name="source">the plaintext string</param>
        /// <returns>an html string</returns>
        public string ConvertNewLine(string source) {
            if (!string.IsNullOrEmpty(source)) {
                return Regex.Replace(source, "\r?\n", "<br/>");
            } else {
                return "";
            }
        }

        /// <summary>
        /// Split a string using a separator
        /// </summary>
        /// <param name="s">The string to split</param>
        /// <param name="sep">The separator</param>
        /// <returns>The resulted chunks as an xpathnavigator of values</returns>
        public XPathNavigator Split(string s, string sep) {
            string[] seps = { sep};
            string[] values = s.Split(seps, StringSplitOptions.RemoveEmptyEntries);

            XmlDocument docResult = new XmlDocument();
            docResult.AppendChild(docResult.CreateElement("values"));

            if (values.Length > 0) {
                foreach (string value in values) {
                    XmlElement valueElement = docResult.CreateElement("value");
                    valueElement.InnerText = value;
                    docResult.DocumentElement.AppendChild(valueElement);
                }
            }

            return docResult.DocumentElement.CreateNavigator();
        }

        /// <summary>
        /// Gets an XPathNavigator from an url
        /// </summary>
        /// <param name="url">The url used to retrieve the document</param>
        /// <returns>The document's navigator, or an error navigator</returns>
        public XPathNavigator GetXmlDocumentFromUrl(string url) {
            XmlDocument docResult = new XmlDocument();

            try
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
                // wait 4 seconds before shutting down
                req.Timeout = 4000;
                using (Stream s = req.GetResponse().GetResponseStream())
                {
                    docResult.Load(s);
                    s.Close();
                }
            }
            catch (Exception ex) {
                docResult.LoadXml("<error/>");
                if(ex is WebException){
                    docResult.DocumentElement.SetAttribute("status", "", ((WebException)ex).Status.ToString());         
                }

                docResult.DocumentElement.InnerText = ex.Message;
            }

            return docResult.CreateNavigator();
        }
    }
}
